#pragma once
#include <cstddef>
#include <memory>
#include <string>
#include <vector>

#include "TextLine.hpp"

class SourceText;
typedef std::shared_ptr<SourceText> SharedSourceText;

class SourceText {
public:
  static SourceText From(std::string text) {
    return SourceText(text);
  }

public:
  SourceText(std::string text)
      : Text(text) {
    this->Lines = ParseLines(this, text);
  }
  std::vector<TextLine> GetLines() { return this->Lines; }

  size_t GetLength() const { return this->Text.length(); }

  size_t GetLineIndex(size_t position);

  std::string ToString() { return this->Text; }

  std::string ToString(size_t start, size_t length) {
    return this->Text.substr(start, length);
  }

  std::string ToString(TextSpan span) {
    return this->ToString(span.Start, span.Length);
  }

public:
  char operator[](size_t index) { return this->Text[index]; }

private:
  static std::vector<TextLine> ParseLines(SourceText *sourceText,
                                          std::string text);
  static void AddLine(std::vector<TextLine> &result, SourceText *sourceText,
                      size_t position, size_t lineStart, size_t lineBreakWidth);

private:
  std::string Text;
  std::vector<TextLine> Lines;
};